/*
 * lmbo_norblk.h - Generic definitions for LomboTech
 *
 * Copyright (C) 2016-2021, LomboTech Co.Ltd.
 * Author: lomboswer <lomboswer@lombotech.com>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 */
#ifndef __LOMBO_NORBLK_H
#define __LOMBO_NORBLK_H

/* General Control Conmmands */
#define OPCODE_WREN		0x06 /* Write enable */
#define OPCODE_RDSR1		0x05 /* Read status register 1 */
#define OPCODE_RDSR2		0x35 /* Read status register 2 */
#define OPCODE_WRSR1		0x01 /* Write status register 1 */
#define OPCODE_WRSR2		0x31 /* Write status register 2 */
#define OPCODE_CHIP_ERASE	0xc7 /* Erase whole flash chip */
#define OPCODE_RDID		0x9f /* Read JEDEC ID */

/* 3byte address mode nor operation Conmmands */
#define OPCODE_NORM_READ	0x03 /* Read data bytes (low frequency) */
#define OPCODE_FAST_READ	0x0b /* Read data bytes (high frequency) */
#define OPCODE_DUAL_READ	0x3b /* Read data bytes (Dual read) */
#define OPCODE_QUAD_READ	0x6B /* read data bytes (Quad read) */
#define OPCODE_PP		0x02 /* Page program (up to 256 bytes) */
#define OPCODE_QUAD_PP		0x32 /* Quad Page program */
#define OPCODE_BE_4K		0x20 /* Erase 4KiB block */
#define OPCODE_BE_32K		0x52 /* Erase 32KiB block */
#define OPCODE_SE		0xd8 /* Sector erase (usually 64KiB) */

/* 4byte address mode nor operation Conmmands */
#define OPCODE_EN4B		0xb7
#define OPCODE_EX4B		0xe9
#define OPCODE_RDCR		0x15 /* Read configuration register */
#define OPCODE_NORM_READ4B	0x13
#define OPCODE_FAST_READ4B	0x0c
#define OPCODE_DUAL_READ4B	0X3c
#define OPCODE_QUAD_READ4B	0x6c
#define OPCODE_PP4B		0X12
#define OPCODE_QUAD_PP4B	0x32
#define OPCODE_BE4B_4K		0x21
#define OPCODE_BE4B_32K		0x5c
#define OPCODE_SE4B		0xdc

/* Status or Configuration Register bits */
#define WIP_BIT			(0)
#define WEL_BIT			(1)
#define QE_BIT6			(6) /* status register1 quad enable flag bit */
#define QE_BIT1			(1) /* status register2 quad enable flag bit */
#define CFG_ADDR_4BYTE_BIT	(5) /* config register 4byte addr flag bit */

/* Define max times to check status register before we give up. */
#define	MAX_READY_WAIT_JIFFIES	(240 * HZ) /* 120s max chip erase */

#define BUF_READ_SIZE		(128 * 1024)

/*
 * struct flash_info - spi nor flash massage description.
 * @jedec_id: spi nor jedec_id.
 * @ext_id: spi nor ext_id.
 * @sector_size: spi nor sector size.
 * @n_sectors: spi nor number of sector.
 * @page_size: max write bytes for one program.
 * @addr_width: 3 bytes or 4 bytes address.
 * @flag:spi nor flag.
 * @SECT_4K:determine whether to perform 4 k erasure.
 */
struct flash_info {
	u32		jedec_id;
	int		ext_id;

	int		sector_size;
	int		n_sectors;

	int		page_size;
	int		addr_width;

	unsigned int	flags;
#define SECT_4K		0x01
};

#define INFO(_jedec_id, _ext_id, _sector_size, _n_sectors, _flags)	\
	((kernel_ulong_t)&(struct flash_info) {				\
		.jedec_id = (_jedec_id),				\
		.ext_id = (_ext_id),					\
		.sector_size = (_sector_size),				\
		.n_sectors = (_n_sectors),				\
		.page_size = 256,					\
		.flags = (_flags),					\
	})

static const struct spi_device_id lombo_nor_ids[] = {
	{ "gd25q32",	INFO(0xc84016, 0, 64 * 1024,  64, SECT_4K)},
	{ "gd25q64",	INFO(0xc84017, 0, 64 * 1024, 128, SECT_4K)},
	{ "gd25q128",	INFO(0xc84018, 0, 64 * 1024, 256, SECT_4K)},
	{ "gd25q256",	INFO(0xc84019, 0, 64 * 1024, 512, SECT_4K)},

	{ "w25q32",	INFO(0xef4016, 0, 64 * 1024,  64, SECT_4K)},
	{ "w25q64",	INFO(0xef4017, 0, 64 * 1024, 128, SECT_4K)},
	{ "w25q128",	INFO(0xef4018, 0, 64 * 1024, 256, SECT_4K)},

	{ "n25q064",	INFO(0x20ba17, 0, 64 * 1024, 128, SECT_4K)},
	{ "n25q128a",	INFO(0x20ba18, 0, 64 * 1024, 256, SECT_4K)},

	{ "xm25qh128a",	INFO(0x207018, 0, 64 * 1024, 256, SECT_4K)},
	{ "xm25qh128c",	INFO(0x204018, 0, 64 * 1024, 256, SECT_4K)},

	{ "mxl12833f",	INFO(0xc22018, 0, 64 * 1024, 256, SECT_4K)},
	{ "mx25635f",	INFO(0xc22019, 0, 64 * 1024, 512, SECT_4K)},
	{ },
};

enum bus_width {
	WIDTH_3BYTE,
	WIDTH_4BYTE,
};

/*
 * struct lombo_norblk - Runtime info holder for SPI norblk device.
 * @spi: Pointer to the SPI device.
 * @lock: mutex lock for sync.
 * @size: Total size of SPI.
 * @page_size: max write bytes for one program.
 * @erase_opcode: erase code, 4K erase or 64K erase.
 * @erasesize: erase size.
 * @read_line: spi device work read line
 * @write_line: spi device work write line
 * @addr_width: 3 bytes or 4 bytes address.
 * @id: nor JEDEC id
 * @freq: transmission frequency
 * @geom：nor as the geometriy model of block device
 */
struct lombo_nor {
	struct spi_device	*spi;
	struct mutex		lock;
	unsigned int		size;
	int			page_size;
	int			erase_opcode;
	int			erase_size;
	int			read_line;
	int			write_line;
	enum bus_width		addr_width;
	unsigned int		id;

	int			freq;
	struct norblk_geometry	geom;
};
#endif /* __LOMBO_NORBLK_H */

